
import 'dart:convert';

import 'package:im_app/im/dao/ImLoginDao.dart';
import 'package:im_app/im/util/ImCacheFactory.dart';

import '../pojo/Enums.dart';
import '../pojo/ImPojo.dart';
import '../socket/ImWebSocket.dart';
import '../socket/ImWebSocketable.dart';
import '../socket/dto/business/Login.dart';
import '../socket/dto/business/PullData.dart';
import '../socket/service/RpcLoginService.dart';
import '../util/ImConstant.dart';
import '../util/ImSingleton.dart';
import '../util/LoggerUtil.dart';
import 'BaseService.dart';
import 'CheckHotMessageTotalService.dart';
import 'SynDataService.dart';

class LoginService extends BaseService {

	final _logger = createLogger();

	Future<LoginResp> login(LoginReq loginReq, LoginType loginType) async {
		if (!ImSingleton.getInstance().isWebSocketInstance) {
			var ip = ImSingleton.getInstance().session.getData("im_ip") as String;
			ImWebSocketable imWebSocket = ImWebSocket("ws://$ip:9290/imWebsocket");
			await imWebSocket.start();
			ImSingleton.getInstance().imWebSocket = imWebSocket;
			// ImSingleton.getInstance().init();
		}

		RpcLoginService rpcLoginService = RpcLoginService();

		LoginResp loginResp = await rpcLoginService.login(loginReq);

		ImSingleton.getInstance()?.loginSuccess(loginResp.userId, loginResp.authCode, loginResp.token, loginResp.authToken,
				loginResp.tenantCode, loginResp.serverDateTime);

		await saveCacheLogin(loginResp, LoginType.password);

		await doLoginSuccessBusiness(loginResp);

		var user = await ImCacheFactory.getInstance().getImUser(loginResp.userId);
		ImSingleton.getInstance().session.putData("LoginUser", user!);

		return loginResp;
	}

	Future<LoginResp> loginByToken(String userId, String token, String tenantCode) async {
		// if (Singleton.getInstance().isLogin()) {
		//   return true;
		// }

		var machineCode = 'android-flutter';

		var loginReq = new LoginTokenReq(userId: userId, token: token, tenantCode: tenantCode, machineCode: machineCode,
				terminalType: TerminalType.hm.name);
		_logger.i("login token, req: ${jsonEncode(loginReq)}", time: DateTime.now());

		var rpcLoginService = new RpcLoginService();

		var loginResp = await rpcLoginService.loginByToken(loginReq);
		_logger.i("login token, resp: ${jsonEncode(loginResp)}");

		ImSingleton.getInstance().loginSuccess(loginResp.userId!, loginResp.authCode, loginResp.token, loginResp
				.authToken, loginResp.tenantCode, loginResp.serverDateTime);

		await saveCacheLogin(loginResp, LoginType.token);

		await doLoginSuccessBusiness(loginResp);

		var user = await ImCacheFactory.getInstance().getImUser(loginResp.userId);
		ImSingleton.getInstance().session.putData("LoginUser", user!);

		return loginResp;
	}

	Future<LoginResp> reconnection() async {
		_logger.i('[Login reconnection], start', time: DateTime.now());
		var tenantCode = ImSingleton.getInstance().session.getData("tenantCode") as String;
		var authToken = ImSingleton.getInstance().session.getData("authToken") as String;
		var reconnection = ReConnection(authToken: authToken!, tenantCode: tenantCode!,
				terminalType: TerminalType.android.name);

		var rpcLoginService = RpcLoginService();

		var loginResp = await rpcLoginService.reconnection(reconnection);
		_logger.i("[Login reconnection], loginResp: ${jsonEncode(loginResp)}", time: DateTime.now());

		ImSingleton.getInstance().loginSuccess(loginResp.userId!, loginResp.authCode, loginResp.token, loginResp
				.authToken, loginResp.tenantCode, loginResp.serverDateTime);

		await saveCacheLogin(loginResp, LoginType.password);

		await doLoginSuccessBusiness(loginResp);

		var user = await ImCacheFactory.getInstance().getImUser(loginResp.userId);
		ImSingleton.getInstance().session.putData("LoginUser", user!);
		return loginResp;
	}

	Future<void> doLoginSuccessBusiness(LoginResp loginResp) async {
		_logger.i("[Login success], doLoginSuccessBusiness start", time: DateTime.now());
		var synDataService = SynDataService();
		await synDataService.synData(loginResp.userId!);
		_logger.i("[Login success], synData success", time: DateTime.now());

		var checkHotMessageService = CheckHotMessageTotalService();

		var startDate = DateTime.now().add(const Duration(days: -ImConstant.IM_SESSION_SHOW_DAYS));
		await checkHotMessageService.checkHotMessageTotal(loginResp.userId!, startDate);
		_logger.i("[Login success], check hot message end", time: DateTime.now());
	}

	Future<void> saveCacheLogin(LoginResp loginResp, LoginType loginType) async {
		ImLoginDao loginDao = ImLoginDao();
		ImLogin? dbLogin = await loginDao.getLoginByUserId(loginResp.userId);
		if (dbLogin != null) {
			ImLogin imLogin = ImLogin(userId: loginResp.userId, loginType: loginType, token: loginResp.token, maskPassword: '111111');
			await loginDao.update(imLogin);
		} else {
			ImLogin imLogin = ImLogin(userId: loginResp.userId, loginType: loginType, token: loginResp.token, maskPassword: '111111');
			await loginDao.insert(imLogin);
		}
	}
}